/*
  ts全称是TypeScript，不是一门新的语言
  只是js的超集，
  理解为就是强类型版本的js

  js广义上来说可以分成三部分：EcmaScript(es)，DOM，BOM
  ts准确来说只是增强了es(js的语法规范)


  ts增加了数据类型，就有了类型推断。
  增强了代码的健壮性，不容易出错了
  ts更适合做大型的项目


  ts有编写时报错，js是执行时报错


  ts的代码浏览器是不认识的，所以需要转成js代码



  1. 全局安装
    cnpm i typescript -g

  2. 编译
    tsc ./src/index.ts --outFile ./dist/index.js

  3. 实时编译
    tsc --init
    tsc --watch 监听
*/ 


// 1. 创建字符串
let str: string = "hi";
str = "123";
console.log(str);

// 当不写类型的时候，也会有自动类型推断（不推荐的）
let str2 = "hello";
// 不加类型也是不能改成其他的数据类型
// str2 = 123;

// 也可以先创建变量，等需要的时候再赋值
let str3: string;
str3 = "123";


// 2. 创建数字
let num: number = 10;
num = 20;


// 3. 创建布尔值
let done: boolean = true;
done = false;


// 4. 创建undefined
// undefined类型只有一个值，就是undefined，不能改成其他的值
let udf: undefined = undefined;
// udf = 77;


// 5. 创建null
// null类型只有一个值，就是null，不能改成其他的值
let nl: null = null;


// 联合类型(或)
let a: string | number | boolean = "a";
a = 3;
a = true;


// const token: null | string = localStorage.getItem("token");
// // if (token) {
// //   token.split("");
// // }
// token?.split("");


// any类型, 任意类型
// 不推荐使用
let b: any = 55;
b = null;


// 数组类型
let arr: number[] = [1,2,3,4,5]; // 常规写法
let arr2: string[] = ["a", "b", "c"];
let arr3: Array<string> = ["a", "b", "c"]; // 泛型写法
let arr4: (number | boolean)[] = [1,2,true];
let arr5: Array<number | boolean> = [1,2,true];
let arr6: any[] = [1,2,true,[7,"abc"]];



// 元组类型
// 数组的扩展(可以规定数组的长度，同时可以规定数组里面的具体的每一项的类型)
let arr7: [number, boolean] = [1, true];



// 对象类型
// 对于对象类型，需要使用interface。接口
interface ObjType {
  name: string;
  age: number;
  num?: number; // ?表示可选字段
  [propname: string]: any; // 索引签名 (只关心上面的属性，剩下的无所谓)
}
let obj: ObjType = {
  name: "zhangsan",
  age: 30,
  a: 11,
  b: true,
  c: () => {},
}
obj.num = 11;


interface Obj2Type {
  id: number | string;
  nm: string;
  img: string;
  preShow: boolean;
  [propname: string]: any;
}
const obj2: Obj2Type = {
  "id": 1607427,
  "haspromotionTag": false,
  "img": "https://p0.pipi.cn/mediaplus/friday_image_fe/0fa3345c5c20513de27f07f252bc90550f491.jpg?imageMogr2/quality/80",
  "nm": "炫舞我人生",
  "preShow": false,
  "sc": 0,
  "globalReleased": false,
  "wish": 57,
  "star": "董维恩,陈乐添,杜梵",
  "rt": "2025-11-25",
  "showst": 1,
  "wishst": 0,
  "comingTitle": "11月25日 周二"
}


interface ItemType {
  id: number;
  name: string;
  sex: number;
}
const arr8: ItemType[] = [
  {
    id: 1,
    name: "zhangsan",
    sex: 1
  },
  {
    id: 2,
    name: "lisi",
    sex: 2
  },
]


interface Obj3Type {
  name: string;
  likes: string[];
}
const obj3: Obj3Type = {
  name: "zhangsan",
  likes: ["eat", "sleep"]
}


interface AbcType {
  a: number;
  b: boolean;
}
interface Obj4Type {
  name: string;
  abc: AbcType;
}
const obj4: Obj4Type = {
  name: "wangwu",
  abc: {
    a: 3,
    b: true
  }
}


// interface ChildType {
//   name: string;
//   sex: number;
// }
interface Obj5Type {
  name: string;
  sex: number;
  children?: Obj5Type[];
}
const obj5: Obj5Type = {
  name: "lisi",
  sex: 1,
  children: [
    {
      name: "liwu",
      sex: 2,
    },
    {
      name: "liliu",
      sex: 2
    }
  ]
}



// 枚举类型
// 对象的扩展(类似于对象，可以通过key找到value，也可以通过value找到key)
enum Color {
  Red = 10,
  Green = 20,
  Blue = 30,
}
console.log(Color["Red"]);
console.log(Color["Green"]);
console.log(Color["Blue"]);
console.log(Color[10]);
console.log(Color[20]);
console.log(Color[30]);



// 函数类型
// 函数类型要写的是函数返回值的类型
function fn(): number {
  return 123
}
// 当函数没有返回值的时候，返回void类型
function fn2(): void {
  console.log(123);
}
const fn3 = (): number => {
  return 123
}
const fn4: () => number = (): number => {
  return 123
}

// 带参数的函数
const fn5 = (a: number, b: number): number => {
  return a + b
}
fn5(3, 4);
// 可以加问号，表示是可选参数
const fn6 = (a: string, b?: string): string => {
  return a
}
fn6("hello");
fn6("hello", "world");

// 函数报错或者死循环，那么返回never类型
// const fn7 = (): never => {
//   while(true) {}
// }
const fn8 = (): number | never => {
  try {
    // ....
    return 123
  } catch(err:any) {
    throw new Error(err)
  }
}



// 泛型类型
// 函数的扩展,将类型作为一个参数进行传递
const fn9 = <T>(a: T, b: T) => {
  return 123
}
// function fn9<T>(a: T, b: T) {
//   return 123
// }
fn9<string>("a", "b");
fn9<number>(3, 4);




// const count = ref<number>(10);

// function ref<T>(n: T) {
//   return {
//     // ...
//     value: n
//   }
// }
